#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osg/ImageStream>
#include <osg/Texture2D>
#include <osg/AutoTransform>

// #define RTSP 1
#define USE_AT 1
#define USE_CreateImageGeometry 1

osg::Geometry *CreateImageGeometry(osg::Image *pImage, double dHeadingRadian = 0, const osg::Vec2s &vec2sPixelOffsets = osg::Vec2s(0, 0), unsigned nTextureUnit = 0)
{
    osg::Texture2D *_pTexture2D = new osg::Texture2D();
    _pTexture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
    _pTexture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
    _pTexture2D->setResizeNonPowerOfTwoHint(false);
    _pTexture2D->setImage(pImage);

    osg::StateSet *_pStateSet = new osg::StateSet;
    _pStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
    _pStateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
    _pStateSet->setTextureAttributeAndModes(nTextureUnit, _pTexture2D, osg::StateAttribute::ON);
    _pStateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);

    osg::Geometry *_pGeometry = new osg::Geometry();
    _pGeometry->setUseVertexBufferObjects(true);

    float x0 = (float)vec2sPixelOffsets.x() - pImage->s() / 2.0;
    float y0 = (float)vec2sPixelOffsets.y() - pImage->t() / 2.0;

    osg::Vec3Array *verts = new osg::Vec3Array(4);
    osg::ImageStream *imageStream = dynamic_cast<osg::ImageStream *>(pImage);
    if (imageStream)
    {
        (*verts)[0].set(x0, -y0, 0);
        (*verts)[1].set(x0 + pImage->s(), -y0, 0);
        (*verts)[2].set(x0 + pImage->s(), -y0 - pImage->t(), 0);
        (*verts)[3].set(x0, -y0 - pImage->t(), 0);
    }
    else
    {
        (*verts)[0].set(x0, y0, 0);
        (*verts)[1].set(x0 + pImage->s(), y0, 0);
        (*verts)[2].set(x0 + pImage->s(), y0 + pImage->t(), 0);
        (*verts)[3].set(x0, y0 + pImage->t(), 0);
    }

    if (dHeadingRadian != 0.0)
    {
        osg::Matrixd rot;
        rot.makeRotate(dHeadingRadian, 0.0, 0.0, 1.0);
        for (unsigned int i = 0; i < 4; i++)
        {
            (*verts)[i] = rot * (*verts)[i];
        }
    }
    _pGeometry->setVertexArray(verts);
    // osg::Vec3Array *normal = new osg::Vec3Array(1);
    // normal->at(0) = osg::Vec3(-1.0, 0, 0)^osg::Vec3(0, 0, 1.0);
    //_pGeometry->setNormalArray(normal);

    osg::Vec2Array *tcoords = new osg::Vec2Array(4);
    (*tcoords)[0].set(0, 0);
    (*tcoords)[1].set(1, 0);
    (*tcoords)[2].set(1, 1);
    (*tcoords)[3].set(0, 1);
    _pGeometry->setTexCoordArray(nTextureUnit, tcoords);

    osg::Vec4Array *colors = new osg::Vec4Array(1);
    (*colors)[0].set(1.0f, 1.0f, 1.0, 1.0f);
    _pGeometry->setColorArray(colors);
    _pGeometry->setColorBinding(osg::Geometry::BIND_OVERALL);
    _pGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));

    _pGeometry->setStateSet(_pStateSet);
    return _pGeometry;
}

osg::Geode *CreateImageNode(osg::Image *pImage, double dImageHeadingRadian = 0)
{
    osg::Geode *pNodeImage = new osg::Geode;
    osg::Geometry *pGemoetryImage = CreateImageGeometry(pImage, dImageHeadingRadian);
    pNodeImage->addDrawable(pGemoetryImage);
    return pNodeImage;
}

int main()
{
#ifdef RTSP
    osg::ref_ptr<osgDB::ReaderWriter> rw = osgDB::Registry::instance()->getReaderWriterForExtension("ffmpeg");
    osgDB::ReaderWriter::ReadResult rr = rw->readImage("rtsp://127.0.0.1:8554/test.264");
    osg::ref_ptr<osg::Image> image = rr.getImage();
#else
    // 注册插件
    osgDB::Registry::instance()->addFileExtensionAlias("mp4", "ffmpeg"); // 本地视频(自己选择视频路径)
    osg::ref_ptr<osg::Image> image = osgDB::readImageFile("data/realshort.mp4");
#endif
    osg::ImageStream *imageStream = dynamic_cast<osg::ImageStream *>(image.get());
    if (imageStream)
    {
        imageStream->play();
    }

#ifdef USE_CreateImageGeometry
    // 添加到场景
    osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
    osg::ref_ptr<osg::AutoTransform> at = new osg::AutoTransform;
    at->addChild(CreateImageNode(image.get()));
    at->setAutoRotateMode(osg::AutoTransform::ROTATE_TO_SCREEN);
    viewer->setSceneData(at.get());
#else

    // 添加到四边形
    osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
    texture->setImage(image.get());
    osg::ref_ptr<osg::Drawable> quad = osg::createTexturedQuadGeometry(
#ifdef USE_AT
        osg::Vec3(0, 1.5, 0), osg::Vec3(4.0f, 0.0f, 0.0f), osg::Vec3(0.0f, -3.0f, 0.0f));
#else
        osg::Vec3(), osg::Vec3(4.0f, 0.0f, 0.0f), osg::Vec3(0.0f, 0.0f, -3.0f));
#endif
    quad->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture.get());

    // 添加到场景
    osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;

#ifdef USE_AT
    // 添加到geode
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    geode->addDrawable(quad.get());
    geode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);
    osg::ref_ptr<osg::AutoTransform> at = new osg::AutoTransform;
    at->addChild(geode.get());
    at->setAutoRotateMode(osg::AutoTransform::ROTATE_TO_SCREEN);
    viewer->setSceneData(at.get());
#else
    // 创建一个Billboard的对象
    osg::ref_ptr<osg::Billboard> billboard = new osg::Billboard();
    billboard->setMode(osg::Billboard::POINT_ROT_EYE);
    // 添加Drawable,并设置其位置，默认位置为osg::Vec3(0.0f,0.0f,0.0f)
    billboard->addDrawable(quad.get(), osg::Vec3(0.0f, 0.0f, 0.0f));
    billboard->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);
    viewer->setSceneData(billboard.get());
#endif
#endif
    viewer->run();
}